import type { Ref } from "vue";
import type { AuditFields } from "./audit-fields";

/** 比较逻辑 */
export enum Comparator {
  EQ,
  NOT_EQ,
  LT,
  LT_EQ,
  GT,
  GT_EQ,
  LIKE,
  NOT_LIKE,
  IN,
  BETWEEN,
  IS_NULL,
  IS_NOT_NULL,
  IS_TRUE,
  IS_FALSE,
}

/** 高级查询条件 */
export type AdvancedCondition<T> = { f: keyof T; c: Comparator; v?: Array<T[keyof T]> };

/** 条件逻辑 */
export type Operator = "AND" | "OR" | null;

/** 高级查询过滤器 */
export class AdvancedFilter<T extends object> {
  /** operator，逻辑关系 */
  o: Operator = null;
  /** conditions，条件集合 */
  c: AdvancedCondition<T>[] = [];
  /** filters，过滤器集合 */
  f: AdvancedFilter<T>[] | null = null;

  constructor(query?: Query<T>, op: Operator = "AND") {
    if (query) {
      const keys = Object.keys(query);
      const { IS_NULL, IN, LIKE, EQ } = Comparator;

      for (const field of keys) {
        const key = <keyof T>field;
        const val = Reflect.get(query, key);

        if (val === undefined) continue;
        let { value, values, comparator } = val;

        if (value === null && values === undefined) this.c.push({ f: key, c: comparator || IS_NULL });
        if (values !== undefined && values !== null) {
          if (values.length > 0) this.c.push({ f: key, c: comparator || IN, v: values });
        }
        if (value !== undefined && value !== null) {
          this.c.push({ f: key, c: comparator || (typeof value === "string" ? LIKE : EQ), v: [value] });
        }
      }
      this.o = op;
    }
  }

  private add(operator: Operator, other: AdvancedCondition<T>): AdvancedFilter<T>;
  private add(operator: Operator, other: AdvancedFilter<T>): AdvancedFilter<T>;
  private add(operator: Operator, other: any): AdvancedFilter<T> {
    if (!this.o || this.o === operator) {
      if (other instanceof AdvancedFilter) {
        this.c = [...this.c, ...other.c];
      } else {
        this.c.push(other);
      }
      this.o = operator;
    } else {
      if (!this.f) this.f = [];
      this.f.push(other instanceof AdvancedFilter ? other : new AdvancedFilter<T>().add(operator, other));
    }
    return this;
  }

  public and(other: AdvancedCondition<T>): AdvancedFilter<T>;
  public and(other: AdvancedFilter<T>): AdvancedFilter<T>;
  public and(other: any): AdvancedFilter<T> {
    return this.add("AND", other);
  }

  public or(other: AdvancedCondition<T>): AdvancedFilter<T>;
  public or(other: AdvancedFilter<T>): AdvancedFilter<T>;
  public or(other: any): AdvancedFilter<T> {
    return this.add("OR", other);
  }
}

/** 高级查询排序 */
export type AdvancedSorter<T> = { f: keyof T; s: "ASC" | "DESC" | "DEFAULT" };

/** 高级查询 */
export type AdvancedSearch<T extends object> = { f?: AdvancedFilter<T>; s?: AdvancedSorter<T>[]; g?: Array<keyof T> } | undefined;

/** 分页信息 */
export type PageInfo = { currentPage: number; pageSize: number; total: number; pageCount?: number; offset?: number };
/** 分页结果集 */
export type PagedResult<T> = { data: T[]; pageInfo: PageInfo };

/** 查找重载方法 */
export type InfoOverload = {
  <T extends object>(params?: URLSearchParams): Promise<Ref<T | null>>;
  <T extends object>(params?: AdvancedSearch<T>): Promise<Ref<T | null>>;
};

/** 查找重载方法 */
export type FindOverload = {
  <T extends object>(params?: URLSearchParams): Promise<Ref<T[] | null>>;
  <T extends object>(params?: AdvancedSearch<T>): Promise<Ref<T[] | null>>;
};

/** 分页重载方法 */
export type PageOverload = {
  <T extends object>(params?: URLSearchParams, pager?: PageInfo): Promise<Ref<PagedResult<T> | null>>;
  <T extends object>(params?: AdvancedSearch<T>, pager?: PageInfo): Promise<Ref<PagedResult<T> | null>>;
};

/** T 类型的查询类型 */
export type Query<T extends object> = Partial<Omit<{ [P in keyof T]: { value?: T[P]; values?: T[P][]; comparator?: Comparator } }, keyof AuditFields>>;

/** T 类型的表单类型 */
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
export type Form<T> = Omit<{ [P in keyof T]: T[P] extends Primitive ? T[P] : Form<Required<T>[P]> }, keyof AuditFields>;
